跳到主要内容

利用 Shell 脚本和 systemd 服务实现 Proxmox VE 日志监控与推送

· 阅读需 8 分钟
木易(OwenYang)

现代 IT 基础设施越来越复杂,其中日志管理和监控更成为运维人员的重要任务之一。本文将介绍如何通过 Shell 脚本实时监控 Proxmox VE 系统日志,并将监控结果推送到 Bark 应用。同时,我们会利用 systemd 服务确保脚本在系统启动时自动运行,一旦出现异常自动重启,确保服务的稳定运行。

场景描述

在 Proxmox VE 环境中,系统日志中可能会出现一些异常信息需要及时处理。为了保证系统运行稳定,我们需要一种实时监控日志,并在检测到关键字时立即通知或报警的机制。通过 Shell 脚本和 Bark 推送,我们可以高效地实现这一目标。

步骤概览

  1. 编写 Shell 脚本 monitor_pve_logs.sh,实时监控系统日志。
  2. 创建符号链接,将脚本链接到 /usr/local/bin/ 目录。
  3. 创建 systemd 服务单元文件,以确保脚本在系统启动时自动运行。
  4. 启用并启动 systemd 服务。

编写 Shell 脚本 monitor_pve_logs.sh

以下是完整的 Shell 脚本,用于监听 Proxmox VE 的系统日志文件 /var/log/syslog。一旦检测到预定义的关键字,将截取该日志行的前后若干行,并通过 Bark API 推送通知。

#!/bin/bash

# 校验 jq 是否安装,如果未安装则退出脚本
if ! command -v jq &> /dev/null; then
echo "jq 命令未找到,请先安装 jq。" >&2
exit 1
fi

# 配置部分
KEYWORDS=("关键字1" "关键字2" "关键字3") # 要监控的关键字列表
LINES_BEFORE=5 # 关键字前的行数
LINES_AFTER=5 # 关键字后的行数
BARK_API_URL="https://api.day.app/push"
BARK_DEVICE_KEY="<your_key>" # 替换为你的 Bark 设备 key
GROUP="pve" # Bark 分组
MAX_ALERTS=10 # 每分钟最多推送次数
ALERT_INTERVAL=60 # 防抖时间窗口(秒)
MIN_TIME_DELTA=10 # 最小推送时间间隔(秒)

# 存储时间戳的数组,用于防抖
timestamps=()

# 存储已经推送过的日志行的集合
declare -A sent_lines

# 最近一次推送的时间戳,用于延迟推送
last_push_time=0

# 判断日志行是否包含任意关键字
contains_keyword() {
local line="$1"
for keyword in "${KEYWORDS[@]}"; do
if echo "$line" | grep -qi "$keyword"; then
return 0
fi
done
return 1
}

# 解析日志行中的时间戳
extract_timestamp() {
local line="$1"
echo "$line" | awk '{print $1 "T" $2}'
}

# 监听 /var/log/syslog
tail -F /var/log/syslog | while read -r LINE; do
# 检查是否包含任意关键字
if contains_keyword "$LINE"; then
# 检查该行是否已经推送过
if [[ ${sent_lines["$LINE"]} ]]; then
continue
fi
# 将该行标记为已推送
sent_lines["$LINE"]=1

# 获取当前日志行的时间戳
log_timestamp=$(extract_timestamp "$LINE")
# 去掉尾部的时区部分
log_timestamp="${log_timestamp%+*}"
log_time=$(date -d "$log_timestamp" +%s 2>/dev/null)

# 检查日期解析是否成功
if [[ -z "$log_time" ]]; then
echo "警告:无法解析时间戳 '$log_timestamp',跳过该日志行。"
continue
fi

# 检查时间间隔是否小于最小时间间隔
if (( log_time - last_push_time < MIN_TIME_DELTA )); then
echo "警告:时间间隔小于 $MIN_TIME_DELTA 秒,跳过推送。"
continue
fi

# 获取当前时间戳(秒)
current_time=$(date +%s)

# 过滤掉时间窗口之外的旧时间戳
timestamps=($(for ts in "${timestamps[@]}"; do
if (( current_time - ts < ALERT_INTERVAL )); then
echo "$ts"
fi
done))

# 检查是否超过推送限制
if (( ${#timestamps[@]} < MAX_ALERTS )); then
# 将当前时间戳添加到数组中
timestamps+=("$current_time")

# 更新最近一次推送的时间戳
last_push_time=$log_time

# 获取当前日志文件名和行号
LOG_FILE="/var/log/syslog"

# 使用 awk 获取日志行号
LINE_NUMBER=$(awk -v line="$LINE" '$0 == line {print NR; exit}' "$LOG_FILE")

# 确保 START_LINEEND_LINE 不小于 1,且在日志文件行数范围内
START_LINE=$((LINE_NUMBER - LINES_BEFORE))
((START_LINE < 1)) && START_LINE=1
END_LINE=$((LINE_NUMBER + LINES_AFTER))

# 截取前后 n 行的日志
LOG_SNIPPET=$(sed -n "${START_LINE},${END_LINE}p" "$LOG_FILE")

# 对日志信息进行字符串转义
ESCAPED_MESSAGE=$(echo "$LOG_SNIPPET" | jq -sR .)

# 通过 Bark API 发送通知
curl -X "POST" "$BARK_API_URL" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"body": '"$ESCAPED_MESSAGE"',
"title": "PVE系统日志异常",
"group": "'"$GROUP"'",
"device_key": "'"$BARK_DEVICE_KEY"'"
}' > /dev/null 2>&1
else
echo "警告:每分钟推送次数超过限制,跳过推送。"
fi
fi
done

创建符号链接

将脚本文件链接到 /usr/local/bin/ 目录,以便 systemd 服务可以方便地找到脚本:

sudo ln -s ~/scripts/monitor_pve_logs.sh /usr/local/bin/monitor_pve_logs.sh

创建 systemd 服务单元文件

为了使脚本作为服务运行,并在系统启动时自动运行,我们需要创建 systemd 服务单元文件。

创建服务单元文件 monitor_pve_logs.service 并放置在 /etc/systemd/system/ 目录下:

sudo nano /etc/systemd/system/monitor_pve_logs.service

在文件中添加以下内容:

[Unit]
Description=Proxmox VE Logs Monitor Service
After=network.target

[Service]
ExecStart=/usr/local/bin/monitor_pve_logs.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target

启用并启动服务

按照以下步骤启用并启动 systemd 服务:

  1. 重新加载 systemd 配置:

    sudo systemctl daemon-reload
  2. 启用服务,使其在启动时自动运行:

    sudo systemctl enable monitor_pve_logs.service
  3. 启动服务:

    sudo systemctl start monitor_pve_logs.service
  4. 检查服务的状态,确保其正常运行:

    sudo systemctl status monitor_pve_logs.service

你应该看到类似如下的输出,显示服务正在运行:

● monitor_pve_logs.service - Proxmox VE Logs Monitor Service
Loaded: loaded (/etc/systemd/system/monitor_pve_logs.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2024-09-14 23:00:00 UTC; 1min 30s ago
Main PID: 12345 (monitor_pve_logs.sh)
CGroup: /system.slice/monitor_pve_logs.service
├─12345 /bin/bash /usr/local/bin/monitor_pve_logs.sh
└─12346 tail -F /var/log/syslog

手动停止和禁用服务

  • 手动停止服务

    sudo systemctl stop monitor_pve_logs.service
  • 手动禁用服务

    sudo systemctl disable monitor_pve_logs.service

调试和日志信息

如果需要查看服务的日志信息,可以使用 journalctl 命令:

sudo journalctl -u monitor_pve_logs.service

总结

通过上述步骤,您可以为 Proxmox VE 配置一个实时监控日志的 Shell 脚本,并结合 systemd 服务确保脚本在系统启动时自动运行及异常恢复。这一方案不仅适用于 Proxmox VE,也适用于其他需要实时监控日志并及时通知的系统环境。希望这篇文章能为您的运维工作提供帮助和参考。